package com.wink.service;

import com.google.code.morphia.query.Query;
import com.google.gson.Gson;
import com.mongodb.MongoException;

import com.storage.mongo.DBInterface;
import com.storage.mongo.ETopic;
import com.storage.mongo.Echarity;
import com.wink.charity.Charity;
import com.wink.charity.CharityList;
import com.wink.common.Login;
import com.wink.common.Publish;
import com.wink.dt.Comment;
import com.wink.dt.Topic;
import com.wink.dt.TopicList;
import com.wink.event.Event;
import com.wink.event.EventList;
import com.wink.subscribe.SubscribeEmailTask;
import com.wink.subscribe.Subscription;
import com.wink.subscribe.SubscriptionList;


import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;

import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.wink.client.Resource;
import org.apache.wink.client.RestClient;
import org.apache.wink.common.model.synd.SyndContent;
import org.apache.wink.common.model.synd.SyndEntry;
import org.apache.wink.common.model.synd.SyndText;
import org.apache.wink.server.utils.LinkBuilders;

import org.apache.wink.json4j.JSONException;
import org.apache.wink.providers.json.JsonJAXBProvider;
import org.apache.wink.providers.json.JsonProvider;
import org.apache.wink.providers.json.JsonArrayProvider;

public class CommunityServicesImpl implements CommunityServices {

	// POS singleton (better solution should be
	// provided!)
	private static CommunityServicesImpl svc;
	
	// simulate persistent storage (singleton svc ensures only one copy)

	private Topic topic = new Topic();
	

	public synchronized static CommunityServicesImpl getInstance() {
		if (svc == null) {
			System.out.println("---> SVR: creating demo data");

			// TODO here we should add the storage the service 
			svc = new CommunityServicesImpl();

		}

		return svc;
	}	
	
	@Override
	public String getServices() {	
		System.out.println("---> SVR: In getServices ");
		String[] services =  {"DiscussionThreads", "Events"};
		ToConverter obj = new ToConverter(services);		
		Gson gson = new Gson();
		String json = gson.toJson(obj);		
		return json;
	}
		
	//Charity actions
	@Override
	public String listAllCharity() throws UnknownHostException, MongoException {
		
		DBInterface di = new DBInterface();
		
		System.out.println("---> SVR: In listAllCharity ");
		List<Echarity> list = di.listCharity();
		ArrayList<Charity> listCharity = new ArrayList<Charity>();
		for(Echarity c : list)
		{
			Charity charity = new Charity();
			charity.setCharityID(c.getId().toString());
			charity.setCommunityID(c.getCommunityID());
			charity.setCreatedBy(c.getCreatedUser());
			charity.setDescription(c.getCharityDescription());
			charity.setName(c.getCharityName());
			charity.setAmount(c.getTotalAmount());
			listCharity.add(charity);
		}

		CharityList cList = new CharityList(listCharity);
		String hostJson = CharityList.toJson(cList);
		
		// discover and list objects form other communities
		// get Charities from other communities
		String[] guestCommunities = di.getGuestCommunities();
		if (guestCommunities != null) {
		
		// get connection details for other communities
		for (int i = 0; i<guestCommunities.length; i++)
		{
			// iterate through each and get charity list
			String gList = listGuestObjects(guestCommunities[i], "charity");	
			hostJson = combineJsonArray(hostJson, gList,  "charity");
	}			
	}
		return hostJson;
	}	
	
	
	
	@Override
	public String createCharity(String json) throws UnknownHostException, MongoException  {
		DBInterface di = new DBInterface();
		
		Charity charity = Charity.fromJson(json);
		System.out.println("---> SVR: In createCharity");
		System.out.println("---> SVR: createCharity --> "
				+ ", Charity Name" + charity.getName() 
				+ ", Charity Description" + charity.getDescription());
		
		di.createCharity(charity.getName(), charity.getDescription(), charity.getCreatedBy(), charity.getAmount(),charity.getCommunityID());
		return Charity.toJson(charity);
	}
	@Override
	public String GetCharityByName(String name) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		Charity charity = new Charity();
		System.out.println("---> SVR: In GetCharityByName");
		System.out.println("---> SVR: In parm " + name);
		charity = Charity.fromJson(name);
		Query<Echarity> query = di.getCharityDetails(charity.getName());
		
		for(Echarity c: query)
		{
			charity.setName(c.getCharityName());
			charity.setDescription(c.getCharityDescription());
			charity.setCommunityID(c.getCommunityID());
			charity.setCharityID(c.getId().toString());
			charity.setCommunityID(c.getCommunityID());
			charity.setCreatedBy(c.getCreatedUser());
			charity.setDescription(c.getCharityDescription());
			charity.setName(c.getCharityName());
			charity.setAmount(c.getTotalAmount());
			
		}
		
		return charity.toJson(charity);
	}
	
	@Override
	public String GetParticularCharity(@PathParam("id") String id) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		Charity charity = new Charity();
		
		System.out.println("-----> SVR: In GetCharityByID");
		System.out.println("---> SVR: In parm " + id);
		List<Echarity> list = di.getParticularCharity(id);
		
		for(Echarity c: list)
		{
			charity.setName(c.getCharityName());
			charity.setDescription(c.getCharityDescription());
			charity.setCommunityID(c.getCommunityID());
			charity.setCharityID(c.getId().toString());
			charity.setCommunityID(c.getCommunityID());
			charity.setCreatedBy(c.getCreatedUser());
			charity.setDescription(c.getCharityDescription());
			charity.setName(c.getCharityName());
			charity.setAmount(c.getTotalAmount());
		}
		
		return charity.toJson(charity);
	}
		
	@Override
	public String donate(String ID,String charity) throws NumberFormatException, UnknownHostException, MongoException {	
		DBInterface di = new DBInterface();
		System.out.println("---> SVR: In donate"  );
		Charity c = Charity.fromJson(charity);
		System.out.println("---> SVR: Donate to  --> "
				+ ", Charity Name " + c.getCreatedBy() 
				+ ", amt " + c.getAmount() +"ID" + ID);
		
		int returnvalue = di.donateCharity(ID,Integer.parseInt(c.getAmount()), c.getCreatedBy(),c.getCommunityID());;
		Charity ch = new Charity();
		if(returnvalue==1)
		{
			ch.setResponse("Success");
		}
		else
		{
			ch.setResponse("Failure");
		}
		
		return Charity.toJson(ch);
	}	
	
	//DT actions
	@Override
	public String listAllDiscussion() throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		ArrayList<Topic> list = new ArrayList<Topic>();
		System.out.println("---> SVR: In listAllDiscussion");
		
		//get Topic list from local community
		Query<com.storage.mongo.ETopic> query = di.getTopics();		
		for(ETopic t : query)
		{
			Topic topic = new Topic();
			topic.setTopicTitle(t.getTopicTitle());
			topic.setTopicdescription(t.getTopicContent());
			topic.setCreatedBy(t.getCreatedUser());
			topic.setCommunityID(t.getCommunityID());
			topic.setDate(t.getCreatedDate());
			list.add(topic);			
		}
		
		TopicList tList = new TopicList(list);
		String hostJson = TopicList.toJson(tList);
		
		// discover and list objects form other communities
		// get Topics from other communities
		String[] guestCommunities = di.getGuestCommunities();
		if (guestCommunities != null) {
		
		// get connection details for other communities
		for (int i = 0; i<guestCommunities.length; i++)
		{
			// iterate through each and get charity list
			String gList = listGuestObjects(guestCommunities[i], "topic");	
			hostJson = combineJsonArray(hostJson, gList,  "topic");
		}				
	}
		return hostJson;

	}
	
	@Override
	public String createTopic(String json) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		Topic topic = Topic.fromJson(json);
		System.out.println("---> SVR: In createTopic");
		System.out.println("---> SVR: createTopic --> "
				+ ", Charity Name" + topic.getTopicTitle() 
				+ ", Charity Description" + topic.getTopicdescription());
		
		di.createTopic(topic.getTopicTitle(),topic.getTopicdescription(),topic.getCreatedBy(),topic.getCommunityID());
		
		return Topic.toJson(topic);
	}
	
	@Override
	public void createComment( String json) throws UnknownHostException, MongoException {	
		DBInterface di = new DBInterface();
		Comment comment = Comment.fromJson(json);
		System.out.println("---> SVR: In createComment");
		System.out.println("---> SVR: createComment --> "
				+ ", CommentTopic Name" + comment.getTopicName() 
				+ ", Comment Description" + comment.getComment());

		di.addComments(comment.getTopicName(),comment.getCreatedBy(),comment.getComment());

	}		

	@Override
	public String getTopicByName(@PathParam("name") String name ) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		System.out.println("---> SVR: In getTopicByName, " + name);		
		Topic topic = new Topic();
		Comment comment=new Comment();
		Query<com.storage.mongo.ETopic> query = di.getComments(name);
		for(ETopic t : query)
		{
			
			comment.setComment(t.getComments().getCreatedText().toString());
			topic.addToCommentList(comment);
			topic.setTopicTitle(t.getTopicTitle());
			topic.setCreatedBy(t.getCreatedUser());
			topic.setCommunityID(t.getCommunityID());
			topic.setTopicdescription(t.getTopicContent());
			topic.setDate(t.getCreatedDate());
		}
		
		return Topic.toJson(topic);
		
	}		
	
	@Override
	public String getTopicDetails(@PathParam("name") String name ) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		System.out.println("---> SVR: In getTopicDetails, " + name);	

		Topic topic = new Topic();
		Comment comment=new Comment();
		Query<com.storage.mongo.ETopic> query = di.getComments(name);
		for(ETopic t : query)
		{
			comment.setComment(t.getComments().getCreatedText().toString());
			topic.addToCommentList(comment);
			topic.setTopicTitle(t.getTopicTitle());
			topic.setCreatedBy(t.getCreatedUser());
			topic.setCommunityID(t.getCommunityID());
			topic.setTopicdescription(t.getTopicContent());
			topic.setDate(t.getCreatedDate());
		}
		
		return Topic.toJson(topic);
		
	}
	
	public void subscribe(Subscription sub) throws UnknownHostException, MongoException {
		SubscriptionList sl = new SubscriptionList();
		
		System.out.println("---> SVR: Adding a Subscription for: " + sub.getEmail());
		sl.addSub(sub);
		SubscribeEmailTask task = new SubscribeEmailTask();
		Timer timer = new Timer();
		timer.scheduleAtFixedRate(task, 5000, 5000);
	}

	public String login(String json) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		
		Login login = Login.fromJson(json);
		System.out.println("---> SVR: In login");
		System.out.println("---> SVR: createCharity --> "
				+ ", Login Name" + login.getName());
		
		//di.createLogin(login.getName(), login.getPassword());
		// return community ID
		return Login.toJson(login);
	}
	
	public void publish(String json) throws UnknownHostException, MongoException {
		DBInterface di = new DBInterface();
		
		Publish publish = Publish.fromJson(json);
		System.out.println("---> SVR: In publish");
		System.out.println("---> SVR: createCharity --> "
				+ ", publish server" + publish.getServer()
				+ ", publish port" + publish.getPort());
		
		//di.createPublish(publish.getServer(), publish.getPort());		
	}
	
	public static void main(String[] args) {
		//new CommunityServicesImpl().getServices();
	}
	
	// utility methods
	
	// list "Charity" or "Discussion threads" from other communities
	// here type specifies  "Charity" or "Discussion threads"
	public String listGuestObjects(String connection, String type) {		
		System.out.println("\n **Server --> In demolistObjects");

		try {
			String url = "http://" + connection + "/ReachOut/rest/community/" + type ;
			System.out.println("\n **endPoint: " + url);
			RestClient client = new RestClient();
			Resource resource = client.resource(url);

			@SuppressWarnings("unchecked")
			String list = resource.accept(MediaType.APPLICATION_JSON).get(String.class);
			return list;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return  null;
	}
	
private String combineJsonArray(String hostJson, String guestJson,  String type) {
		
		if (type.equalsIgnoreCase("charity")) {
			CharityList hostList = CharityList.fromJson(hostJson);
			CharityList guestList = CharityList.fromJson(guestJson);
			hostList.getList().addAll(guestList.getList());
			return CharityList.toJson(hostList);
		}		
		else if (type.equalsIgnoreCase("topic")) {
			TopicList hostList = TopicList.fromJson(hostJson);
			TopicList guestList = TopicList.fromJson(guestJson);
			hostList.getList().addAll(guestList.getList());
			return TopicList.toJson(hostList);		
		}
		return null;
	}
	
	
}

class ToConverter
{
	public String service1 ,service2;
	
   public ToConverter(String[] convert)
   {
	   service1 = convert [0];
	   service2 = convert [1];	   
   }
}
